﻿//Copyright (C) 2009  Jaco (ScionBot.com)

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Scion.Core;
using Scion.Library;
using Scion.External;
using Scion.Library.Antiban;
using Scion.Misc;

namespace Scion
{
    public partial class Bot : Form
    {
        public int botNumber;
        public int port;
        public Thread Painter;
        public Stub stub;
        public Client client;
        public Account account;
        private bool closing = false;
        public bool focused = false;

        public Bot(Client c, int number, int portNumber, Account acct)
        {
            botNumber = number;
            client = c;
            account = acct;
            port = portNumber;
            InitializeComponent();
        }

        public void Kill()
        {
            stub.Stop();
        }

        private void Bot_Load(object sender, EventArgs e)
        {
            this.Dock = DockStyle.Fill;
            this.SizeChanged += new EventHandler(Bot_SizeChanged);
            this.FormClosing += new FormClosingEventHandler(Bot_FormClosing);
            this.GotFocus += new EventHandler(Bot_GotFocus);
            this.LostFocus += new EventHandler(Bot_LostFocus);
            this.MouseClick += new MouseEventHandler(Bot_MouseClick);
            this.KeyPress += new KeyPressEventHandler(Bot_KeyPress);
            Application.Idle += new EventHandler(Bot_OnLoaded);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Click += new EventHandler(Bot_Click);
            stub = new Stub(this, botNumber, port, account);
            stub.Start();
            this.Text = "Bot: " + botNumber + " Port: " + port + " | " + stub.botAccount.username;
            ThreadStart ts = delegate { PaintLoop(); };
            Painter = new Thread(ts);
            Painter.Start();
        }

        private void Bot_Click(object sender, EventArgs e)
        {
            API.SetFocus(this.Handle);
        }

        public void UpdateLog(string str)
        {
            if (focused)
            {
                client.textBox1.Text = str;
                client.textBox1.SelectionStart = client.textBox1.Text.Length;
                client.textBox1.ScrollToCaret();
                client.textBox1.Refresh();
            }
        }

        private void Bot_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (client.humanInputToolStripMenuItem.Checked && focused && !stub.botScript.blockedInput)
            {
                bool returnValue = false;
                int keyCode = (int)e.KeyChar;
                if ((keyCode > 32) && (keyCode < 127))
                {
                    returnValue = stub.keyboard.PressKey(e.KeyChar);
                }
                else if (keyCode == 32)
                {
                    returnValue = stub.keyboard.PressSpace();
                }
                else if (keyCode == 13)
                {
                    returnValue = stub.keyboard.PressEnter(new SleepRandom(20, 100));
                }
                else if ((keyCode == 8))
                {
                    returnValue = stub.keyboard.PressBackSpace(new SleepRandom(5, 20));
                }
                if (!returnValue)
                {
                    MessageBox.Show("Could not process key press.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (client.humanInputToolStripMenuItem.Checked && focused && !stub.botScript.blockedInput)
            {
                bool returnValue = false;
                switch (keyData)
                {
                    case Keys.Tab:
                        return true;
                    case Keys.Left:
                        returnValue = stub.keyboard.PressArrow(3, new SleepRandom(90, 110));
                        break;
                    case Keys.Right:
                        returnValue = stub.keyboard.PressArrow(4, new SleepRandom(90, 110));
                        break;
                    case Keys.Down:
                        returnValue = stub.keyboard.PressArrow(2, new SleepRandom(90, 110));
                        break;
                    case Keys.Up:
                        returnValue = stub.keyboard.PressArrow(1, new SleepRandom(90, 110));
                        break;
                }
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void Bot_MouseClick(object sender, MouseEventArgs e)
        {
            if (client.humanInputToolStripMenuItem.Checked && focused && !stub.botScript.blockedInput)
            {
                bool returnValue = false;
                if (e.Button == MouseButtons.Left)
                {
                    returnValue = stub.mouse.MoveClick(new PointRandom(e.X, e.Y, 2), true);
                }
                else if (e.Button == MouseButtons.Right)
                {
                    returnValue = stub.mouse.MoveClick(new PointRandom(e.X, e.Y, 2), false);
                }
                if (!returnValue)
                {
                    MessageBox.Show("Could not process mouse press.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void Bot_OnLoaded(object sender, EventArgs e)
        {
            Application.Idle -= new EventHandler(Bot_OnLoaded);
            External.API.SetFocus(this.Handle);
        }

        private void Bot_GotFocus(object sender, EventArgs e)
        {
            focused = true;
            stub.botLog.Flush();
        }

        private void Bot_LostFocus(object sender, EventArgs e)
        {
            focused = false;
        }

        private void Bot_FormClosing(object sender, FormClosingEventArgs e)
        {
            closing = true;
            Kill();
            client.textBox1.Text = "";
        }

        private Image Process(Bitmap bmp)
        {
            Graphics g = Graphics.FromImage((Image)bmp);
            foreach (PaintObject po in stub.botGraphics.objects)
            {
                if (!po.IsDiposed)
                {
                    switch (po.type)
                    {
                        case (int)PaintObject.PaintType.Text:
                            Font f = new Font("Microsoft Sans Serif", 10);
                            g.DrawString(po.text, f, po.brush, (PointF)po.position);
                            break;
                        case (int)PaintObject.PaintType.Image:
                            g.DrawImage(po.image, po.position);
                            break;
                        case (int)PaintObject.PaintType.Rectangle:
                            if (po.full)
                                g.FillRectangle(po.brush, po.rect);
                            else
                                g.DrawRectangle(new Pen(po.brush), po.rect);
                            break;
                        case (int)PaintObject.PaintType.Line:
                            g.DrawLine(po.pen, po.position, po.position2);
                            break;
                        case (int)PaintObject.PaintType.Ellipse:
                            if (po.full)
                                g.FillEllipse(new SolidBrush(po.pen.Color), po.rect);
                            else
                                g.DrawEllipse(po.pen, po.rect);
                            break;
                    }
                }
            }
            g.Flush();
            g.Dispose();
            return bmp;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                if (!closing)
                {
                    Graphics g = this.CreateGraphics();
                    Bitmap bmp = stub.botCanvas.GetCanvas(0);// stub.botOffscreen.CaptureRawWindow();
                    Image im = Process(bmp);
                    g.DrawImage(im, new Point(0, 0));
                    im.Dispose();
                    bmp.Dispose();
                    g.Dispose();
                    GC.Collect();
                }
            }
            catch
            {
            }
            base.OnPaint(e);
        }

        private void PaintLoop()
        {
            while (true)
            {
                if (focused && !closing)
                {
                    this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), new Rectangle(new Point(0, 0), this.Size)));
                    System.Threading.Thread.Sleep(ScionSettings.RefreshInterval);
                }
                else
                {
                    if (closing)
                    {
                        return;
                    }
                }
                System.Threading.Thread.Sleep(ScionSettings.RefreshInterval);
            }
        }

        private void Bot_SizeChanged(object sender, EventArgs e)
        {
            this.ClientSize = new Size(765, 503);
        }
    }
}
